package com.wish.nettyhttpsimple;

import com.wish.common.MyUtils;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;

/**
 * @author tantexian
 * @since 2016/7/14
 */
public class HttpFileServer {

    private static final String defaultUrl = "/src/main/java/com/wish/";

    public static void main(String[] args) {
        String host = MyUtils.getDefaultServerAddr();
        int port = MyUtils.getDefaultPort();
        new HttpFileServer().run(host, port, defaultUrl);
    }


    public void run(final String host, final int port, final String url){
        // 创建NIO线程组（Reactor封装），用于处理网络事件
        // 处理客户端连接NIO线程组
        NioEventLoopGroup accetpNioEventLoopGroup = new NioEventLoopGroup();
        // 处理网络IO事件NIO线程组
        NioEventLoopGroup handleNioEventLoopGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(accetpNioEventLoopGroup, handleNioEventLoopGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // Netty中，可以注册多个handler。ChannelInboundHandler按照注册的先后顺序执行；ChannelOutboundHandler按照注册的先后顺序逆序执行
                            // http请求消息解码器
                            pipeline.addLast("HttpRequestDecoder", new HttpRequestDecoder());
                            // 将多个消息换换为单一的FullHttpRequest或者FullHttpRespose
                            pipeline.addLast("HttpObjectAggregator", new HttpObjectAggregator(65536));
                            // http请求消息编码器
                            pipeline.addLast("HttpResponseEncoder", new HttpResponseEncoder());
                            // 支持异步发送大码流，防止java内存溢出
                            pipeline.addLast("ChunkedWriteHandler", new ChunkedWriteHandler());
                            pipeline.addLast(new HttpFileHandle(url));
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(host, port).sync();
            System.out.println("The http file server started, the url is :" + " http://" + host + ":" + port  + url);
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            accetpNioEventLoopGroup.shutdownGracefully();
            handleNioEventLoopGroup.shutdownGracefully();
        }

    }
}
